/*
 * Copyright (c) 2021 柯华栋
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IPC_DATA_H
#define IPC_DATA_H

#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <gio/gio.h>

// __attribute__((unused))是清除定义没有引用的的警告
#define UNUSED_MARK __attribute__((unused))

#define IPC_MAP_KEY_ID  		"_id"
#define IPC_MAP_KEY_CLIENT 	 	"_client"
#define IPC_MAP_KEY_OBSERVER 	"_observer"
/* 如果map只额外附加一个参数，请使用这个key */
#define IPC_MAP_KEY_VALUE  		"_value"

typedef struct _ipc_u8_array_t 		ipc_u8_array_t;
typedef struct _ipc_s16_array_t 	ipc_s16_array_t;
typedef struct _ipc_s32_array_t 	ipc_s32_array_t;
typedef struct _ipc_s64_array_t 	ipc_s64_array_t;
typedef struct _ipc_float_array_t 	ipc_float_array_t;
typedef struct _ipc_double_array_t 	ipc_double_array_t;
typedef struct _ipc_string_array_t 	ipc_string_array_t;
typedef struct _ipc_map_t 			ipc_map_t;

// 创建array(array对象引用为1,各项都是0) -----------------------------------------
ipc_u8_array_t* 	ipc_u8_array_new(int size);
ipc_s16_array_t* 	ipc_s16_array_new(int size);
ipc_s32_array_t* 	ipc_s32_array_new(int size);
ipc_s64_array_t* 	ipc_s64_array_new(int size);
ipc_float_array_t* 	ipc_float_array_new(int size);
ipc_double_array_t* ipc_double_array_new(int size);
ipc_string_array_t* ipc_string_array_new(int size);

// 创建array(array对象引用为1) ---------------------------------------------------
ipc_u8_array_t* 	ipc_u8_array_new2(uint8_t* value, int size);
ipc_s16_array_t* 	ipc_s16_array_new2(int16_t* value, int size);
ipc_s32_array_t* 	ipc_s32_array_new2(int32_t* value, int size);
ipc_s64_array_t* 	ipc_s64_array_new2(int64_t* value, int size);
ipc_float_array_t* 	ipc_float_array_new2(float* value, int size);
ipc_double_array_t* ipc_double_array_new2(double* value, int size);
ipc_string_array_t* ipc_string_array_new2(const gchar** value, int size);


// 获取条目数量 ------------------------------------------------------------------
int ipc_u8_array_size(ipc_u8_array_t* array);
int ipc_s16_array_size(ipc_s16_array_t* array);
int ipc_s32_array_size(ipc_s32_array_t* array);
int ipc_s64_array_size(ipc_s64_array_t* array);
int ipc_float_array_size(ipc_float_array_t* array);
int ipc_double_array_size(ipc_double_array_t* array);
int ipc_string_array_size(ipc_string_array_t* array);

// 获取位置上的条目 --------------------------------------------------------------
uint8_t ipc_u8_array_get(ipc_u8_array_t* array, int pos);
int16_t ipc_s16_array_get(ipc_s16_array_t* array, int pos);
int32_t ipc_s32_array_get(ipc_s32_array_t* array, int pos);
int64_t ipc_s64_array_get(ipc_s64_array_t* array, int pos);
float   ipc_float_array_get(ipc_float_array_t* array, int pos);
double  ipc_double_array_get(ipc_double_array_t* array, int pos);
const gchar*  ipc_string_array_get(ipc_string_array_t* array, int pos);

// 设置位置上的条目 --------------------------------------------------------------
void ipc_u8_array_set(ipc_u8_array_t* array, int pos, uint8_t value);
void ipc_s16_array_set(ipc_s16_array_t* array, int pos, int16_t value);
void ipc_s32_array_set(ipc_s32_array_t* array, int pos, int32_t value);
void ipc_s64_array_set(ipc_s64_array_t* array, int pos, int64_t value);
void ipc_float_array_set(ipc_float_array_t* array, int pos, float value);
void ipc_double_array_set(ipc_double_array_t* array, int pos, double value);
void ipc_string_array_set(ipc_string_array_t* array, int pos, const gchar* value);

// 添加引用 ----------------------------------------------------------------------
int ipc_u8_array_ref(ipc_u8_array_t* array);
int ipc_s16_array_ref(ipc_s16_array_t* array);
int ipc_s32_array_ref(ipc_s32_array_t* array);
int ipc_s64_array_ref(ipc_s64_array_t* array);
int ipc_float_array_ref(ipc_float_array_t* array);
int ipc_double_array_ref(ipc_double_array_t* array);
int ipc_string_array_ref(ipc_string_array_t* array);

// 删除引用 ----------------------------------------------------------------------
int ipc_u8_array_unref(ipc_u8_array_t* array);
int ipc_s16_array_unref(ipc_s16_array_t* array);
int ipc_s32_array_unref(ipc_s32_array_t* array);
int ipc_s64_array_unref(ipc_s64_array_t* array);
int ipc_float_array_unref(ipc_float_array_t* array);
int ipc_double_array_unref(ipc_double_array_t* array);
int ipc_string_array_unref(ipc_string_array_t* array);

// 创建, 引用, 取消引用, 序列化, 反序列化 map -----------------------------------
ipc_map_t* 			ipc_map_new(void);

// (array对象引用为1, 如果需要销毁，取得数组后需要unref)
ipc_string_array_t* ipc_map_keys(ipc_map_t* map);

int 		ipc_map_ref_cnt(ipc_map_t* map);
int 		ipc_map_ref(ipc_map_t* map);
int 		ipc_map_unref(ipc_map_t* map);

uint8_t*	ipc_map_serial(ipc_map_t* map, int* size);
ipc_map_t* 	ipc_map_unserial(uint8_t* bytes, int size);

GVariant*   ipc_map_to_variant(ipc_map_t* map);
ipc_map_t*  ipc_map_from_variant(GVariant* parameters);

// 删除 ---------------------------------------------------------------------------
void ipc_map_remove(ipc_map_t* map, const gchar* key);

// 查找 --------------------------------------------------------------------------
uint8_t ipc_map_get_u8_3(		ipc_map_t* map, const gchar* key, uint8_t default_value);
int16_t ipc_map_get_s16_3(		ipc_map_t* map, const gchar* key, int16_t default_value);
int32_t ipc_map_get_s32_3(		ipc_map_t* map, const gchar* key, int32_t default_value);
int64_t ipc_map_get_s64_3(		ipc_map_t* map, const gchar* key, int64_t default_value);
float 	ipc_map_get_float_3(	ipc_map_t* map, const gchar* key, float default_value);
double 	ipc_map_get_double_3(	ipc_map_t* map, const gchar* key, double default_value);

// // (注意!!!, 取得的gchar*由map所有，因此不想随着map一起销毁，需要在取得之后主动g_strdup)
const gchar* ipc_map_get_string_3(	ipc_map_t* map, const gchar* key, const gchar* default_value);

// (注意!!!, map不对取得的数组增加引用，因此不想随着map一起销毁，需要在取得之后主动添加引用,
// 就是说map销毁时会unref引用的数组)	
ipc_u8_array_t* 	ipc_map_get_u8_array(		ipc_map_t* map,	const gchar* key);
ipc_s16_array_t* 	ipc_map_get_s16_array(		ipc_map_t* map,	const gchar* key);
ipc_s32_array_t* 	ipc_map_get_s32_array(		ipc_map_t* map, const gchar* key);
ipc_s64_array_t* 	ipc_map_get_s64_array(		ipc_map_t* map, const gchar* key);
ipc_float_array_t* 	ipc_map_get_float_array(	ipc_map_t* map, const gchar* key);
ipc_double_array_t* ipc_map_get_double_array(ipc_map_t* map, const gchar* key);
ipc_string_array_t* ipc_map_get_string_array(ipc_map_t* map, const gchar* key);

// 基本类型查找(默认值0或者NULL) -------------------------------------------------
uint8_t ipc_map_get_u8(ipc_map_t* map, const gchar* key);
int16_t ipc_map_get_s16(ipc_map_t* map, const gchar* key);
int32_t ipc_map_get_s32(ipc_map_t* map, const gchar* key);
int64_t ipc_map_get_s64(ipc_map_t* map, const gchar* key);
float ipc_map_get_float(ipc_map_t* map, const gchar* key);
double ipc_map_get_double(ipc_map_t* map, const gchar* key);

// (注意!!!, 取得的gchar*由map所有，因此不想随着map一起销毁，需要在取得之后主动g_strdup)
const gchar* ipc_map_get_string(ipc_map_t* map, const gchar* key);

// 设置 --------------------------------------------------------------------------
void ipc_map_set_u8(ipc_map_t* map, const gchar* key, uint8_t value);
void ipc_map_set_s16(ipc_map_t* map, const gchar* key, int16_t value);
void ipc_map_set_s32(ipc_map_t* map, const gchar* key, int32_t value);
void ipc_map_set_s64(ipc_map_t* map, const gchar* key, int64_t value);
void ipc_map_set_float(ipc_map_t* map, const gchar* key, float value);
void ipc_map_set_double(ipc_map_t* map, const gchar* key, double value);

// (注意!!!, 设置时map会对value进行g_strdup, 因此value如果是动态创建的，注意销毁)
void ipc_map_set_string(ipc_map_t* map, const gchar* key, const gchar* value);

// (注意!!!, map不对设置的数组增加引用，因此不想随着map一起销毁，需要在设置之前主动添加引用,
// 就是说map销毁时会unref引用的数组)
void ipc_map_set_u8_array(ipc_map_t* map, const gchar* key, ipc_u8_array_t* value);
void ipc_map_set_s16_array(ipc_map_t* map, const gchar* key, ipc_s16_array_t* value);
void ipc_map_set_s32_array(ipc_map_t* map, const gchar* key, ipc_s32_array_t* value);
void ipc_map_set_s64_array(ipc_map_t* map, const gchar* key, ipc_s64_array_t* value);
void ipc_map_set_float_array(ipc_map_t* map, const gchar* key, ipc_float_array_t* value);
void ipc_map_set_double_array(ipc_map_t* map, const gchar* key, ipc_double_array_t* value);
void ipc_map_set_string_array(ipc_map_t* map, const gchar* key, ipc_string_array_t* value);

// (衍生函数)创建带id-value的map -------------------------------------------------------

// 键是IPC_MAP_KEY_ID
ipc_map_t* ipc_map_new_with_id(const gchar* id);

// 键分别是 IPC_MAP_KEY_ID和IPC_MAP_KEY_VALUE (通常用于client_post或者client_send)
ipc_map_t* ipc_map_new_id_u8(const gchar* id, uint8_t value);
ipc_map_t* ipc_map_new_id_s16(const gchar* id, int16_t value);
ipc_map_t* ipc_map_new_id_s32(const gchar* id, int32_t value);
ipc_map_t* ipc_map_new_id_s64(const gchar* id, int64_t value);
ipc_map_t* ipc_map_new_id_float(const gchar* id, float value);
ipc_map_t* ipc_map_new_id_double(const gchar* id, double value);
ipc_map_t* ipc_map_new_id_string(const gchar* id, const gchar* value);
ipc_map_t* ipc_map_new_id_u8_array(const gchar* id, ipc_u8_array_t* value);
ipc_map_t* ipc_map_new_id_s16_array(const gchar* id, ipc_s16_array_t* value);
ipc_map_t* ipc_map_new_id_s32_array(const gchar* id, ipc_s32_array_t* value);
ipc_map_t* ipc_map_new_id_s64_array(const gchar* id, ipc_s64_array_t* value);
ipc_map_t* ipc_map_new_id_float_array(const gchar* id, ipc_float_array_t* value);
ipc_map_t* ipc_map_new_id_double_array(const gchar* id, ipc_double_array_t* value);
ipc_map_t* ipc_map_new_id_string_array(const gchar* id, ipc_string_array_t* value);

// 键是IPC_MAP_KEY_VALUE (通常用于on_send返回)
ipc_map_t* ipc_map_new_u8(uint8_t value);
ipc_map_t* ipc_map_new_s16(int16_t value);
ipc_map_t* ipc_map_new_s32(int32_t value);
ipc_map_t* ipc_map_new_s64(int64_t value);
ipc_map_t* ipc_map_new_float(float value);
ipc_map_t* ipc_map_new_double(double value);
ipc_map_t* ipc_map_new_string(const gchar* value);
ipc_map_t* ipc_map_new_u8_array(ipc_u8_array_t* value);
ipc_map_t* ipc_map_new_s16_array(ipc_s16_array_t* value);
ipc_map_t* ipc_map_new_s32_array(ipc_s32_array_t* value);
ipc_map_t* ipc_map_new_s64_array(ipc_s64_array_t* value);
ipc_map_t* ipc_map_new_float_array(ipc_float_array_t* value);
ipc_map_t* ipc_map_new_double_array(ipc_double_array_t* value);
ipc_map_t* ipc_map_new_string_array(ipc_string_array_t* value);

// 键是IPC_MAP_KEY_OBSERVER (通常用于handle_update中进行server_update2)
ipc_map_t* ipc_map_new_id_observer(const gchar* id, gint64 observer);
ipc_map_t* ipc_map_new_id_observer_u8(const gchar* id, gint64 observer, uint8_t value);
ipc_map_t* ipc_map_new_id_observer_s16(const gchar* id, gint64 observer, int16_t value);
ipc_map_t* ipc_map_new_id_observer_s32(const gchar* id, gint64 observer, int32_t value);
ipc_map_t* ipc_map_new_id_observer_s64(const gchar* id, gint64 observer, int64_t value);
ipc_map_t* ipc_map_new_id_observer_float(const gchar* id, gint64 observer, float value);
ipc_map_t* ipc_map_new_id_observer_double(const gchar* id, gint64 observer, double value);
ipc_map_t* ipc_map_new_id_observer_string(const gchar* id, gint64 observer, const gchar* value);
ipc_map_t* ipc_map_new_id_observer_u8_array(const gchar* id, gint64 observer, ipc_u8_array_t* value);
ipc_map_t* ipc_map_new_id_observer_s16_array(const gchar* id, gint64 observer, ipc_s16_array_t* value);
ipc_map_t* ipc_map_new_id_observer_s32_array(const gchar* id, gint64 observer, ipc_s32_array_t* value);
ipc_map_t* ipc_map_new_id_observer_s64_array(const gchar* id, gint64 observer, ipc_s64_array_t* value);
ipc_map_t* ipc_map_new_id_observer_float_array(const gchar* id, gint64 observer, ipc_float_array_t* value);
ipc_map_t* ipc_map_new_id_observer_double_array(const gchar* id, gint64 observer, ipc_double_array_t* value);
ipc_map_t* ipc_map_new_id_observer_string_array(const gchar* id, gint64 observer, ipc_string_array_t* value);


// (衍生函数)获取id或者value -------------------------------------------------------

const gchar* ipc_map_get_id(ipc_map_t* map);
const gchar* ipc_map_get_client(ipc_map_t* map);

// (注意!!!, map不对取得的数组增加引用，因此不想随着map一起销毁，需要在取得之后主动添加引用,
// 就是说map销毁时会unref引用的数组)	
ipc_u8_array_t* 	ipc_map_get_u8_array_value(		ipc_map_t* map);
ipc_s16_array_t* 	ipc_map_get_s16_array_value(	ipc_map_t* map);
ipc_s32_array_t* 	ipc_map_get_s32_array_value(	ipc_map_t* map);
ipc_s64_array_t* 	ipc_map_get_s64_array_value(	ipc_map_t* map);
ipc_float_array_t* 	ipc_map_get_float_array_value(	ipc_map_t* map);
ipc_double_array_t* ipc_map_get_double_array_value( ipc_map_t* map);
ipc_string_array_t* ipc_map_get_string_array_value( ipc_map_t* map);

// 基本类型查找(默认值0或者NULL) -------------------------------------------------
uint8_t ipc_map_get_u8_value(ipc_map_t* map);
int16_t ipc_map_get_s16_value(ipc_map_t* map);
int32_t ipc_map_get_s32_value(ipc_map_t* map);
int64_t ipc_map_get_s64_value(ipc_map_t* map);
float   ipc_map_get_float_value(ipc_map_t* map);
double  ipc_map_get_double_value(ipc_map_t* map);

// (注意!!!, 取得的gchar*由map所有，因此不想随着map一起销毁，需要在取得之后主动g_strdup)
const gchar* ipc_map_get_string_value(ipc_map_t* map);

extern char _etext, _edata;

// 不需要释放的内存
#define dont_free_memory(p) ((p > &_etext && p < &_edata) || p == NULL)

// 不需要释放的内存，不用复制，直接引用
#define str_check_dup(str)  (dont_free_memory(str) ? (gchar*)str : g_strdup(str))

// 不需要释放的内存就不释放
#define str_check_free(str) {if (!dont_free_memory(str)) g_free(str); }

#endif

